package com.mnsq.im.bean;

import com.alibaba.fastjson.JSONObject;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zj00924
 */
public class SocketsInfoHolder {

    private static final String DEFAULT_ZONE = "defaultZone";

    private static Map<String, List<ChannelHandlerContext>> map = new ConcurrentHashMap<>();

    private static Map<ChannelHandlerContext, String> channelMap = new ConcurrentHashMap<>();

    private static volatile int total = 0;

    public static void addChannel(String group, ChannelHandlerContext channelHandlerContext) {
        group = groupCk(group);
        List<ChannelHandlerContext> channelHandlerContexts = map.get(group);
        if (channelHandlerContexts == null) {
            channelHandlerContexts = new ArrayList<>();
        }
        if (channelHandlerContexts.contains(channelHandlerContext)) {
            return;
        }
        channelHandlerContexts.add(channelHandlerContext);
        map.put(group, channelHandlerContexts);
        channelMap.put(channelHandlerContext, group);
        total++;
    }

    public static void updateChannel(String group, ChannelHandlerContext channelHandlerContext) {
        group = groupCk(group);
        List<ChannelHandlerContext> channelHandlerContexts = map.get(group);
        if (channelHandlerContexts.contains(channelHandlerContext)) {
            channelHandlerContexts.remove(channelHandlerContext);
        }
        channelHandlerContexts.add(channelHandlerContext);
    }

    public static void delChannel(ChannelHandlerContext channelHandlerContext) {
        String s = channelMap.get(channelHandlerContext);
        if (StringUtils.isEmpty(s)) {
            s = DEFAULT_ZONE;
        }
        delChannel(s, channelHandlerContext);
    }

    public static void delChannel(String group, ChannelHandlerContext channelHandlerContext) {
        group = groupCk(group);
        List<ChannelHandlerContext> channelHandlerContexts = map.get(group);
        if (channelHandlerContexts != null && channelHandlerContexts.contains(channelHandlerContext)) {
            channelHandlerContexts.remove(channelHandlerContext);
            total--;
        }
    }

    public static boolean hasChannel(String group, ChannelHandlerContext channelHandlerContext) {
        group = groupCk(group);
        List<ChannelHandlerContext> channelHandlerContexts = map.get(group);
        if (CollectionUtils.isEmpty(channelHandlerContexts)) {
            return false;
        }
        if (channelHandlerContexts.contains(channelHandlerContext)) {
            return true;
        }
        return false;
    }

    public static void sendGroup(SocketMessage socketMessage, String group, ChannelHandlerContext channelHandlerContext) {
        group = groupCk(group);
        List<ChannelHandlerContext> channelHandlerContexts = map.get(group);
        if (!CollectionUtils.isEmpty(channelHandlerContexts)) {
            for (ChannelHandlerContext us : channelHandlerContexts) {
                if (us.equals(channelHandlerContext)) {
                    continue;
                }
                try {
                    sendMsg(us, socketMessage);
                } catch (Exception e) {
                    continue;
                }
            }
        }
    }

    public static void checkSocketValid() {
        for (Map.Entry<String, List<ChannelHandlerContext>> su : map.entrySet()) {
            Iterator<ChannelHandlerContext> iterator = su.getValue().iterator();
            while (iterator.hasNext()) {
                ChannelHandlerContext ust = iterator.next();
                boolean active = ust.channel().isActive();
                if (!active) {
                    iterator.remove();
                    total--;
                }
            }
        }
    }

    private static String groupCk(String group) {
        if (StringUtils.isEmpty(group)) {
            return DEFAULT_ZONE;
        }
        return group;
    }

    public static void sendMsg(ChannelHandlerContext ctx, SocketMessage socketMessage) {
        socketMessage.setTotal(total);
        ctx.channel().writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(socketMessage)));
    }
}
